import { ComponentWithStore } from 'mobx-miniprogram-bindings'
import { userStore } from '@/stores/userStore'
// 导入防抖函数
import { debounce } from 'miniprogram-licia'
// 导入封装好的 swiperCellBehavior 用于处理滑块自动弹回
import swiperCell from '@/behaviors/swipeCell'
import { modal, toast } from '@/utils/extendApi'
import {
  reqAddCart,
  reqCartList,
  reqUpdateChecked,
  reqCheckAllStatus,
  reqDeleteGoods
} from '@/api/cart'
// 引入计算属性和监视器
const computedBehavior = require('miniprogram-computed').behavior
// 该页面使用Component进行构造可以使用ComponentWithStore与store关联,也可以使用behavior的方式
ComponentWithStore({
  // 声明并使用计算属性behavior,和用于处理滑块自动弹回的behavior
  behaviors: [computedBehavior, swiperCell],
  // 绑定仓库并获取仓库中的数据
  storeBindings: {
    store: userStore,
    fields: ['token']
  },
  data: {
    cartList: [], // 购物车商品列表
    emptyDes: '还没有添加商品，快去添加吧～'
  },
  // 计算属性 会被挂载到data上
  computed: {
    // 计算商品是否全选
    // 计算属性不能使用this访问data中的数据，需要使用参数data进行访问
    selectAllStatus(data) {
      if (data.cartList.lenght === 0) return false
      // every() 方法测试一个数组内的所有元素是否都能通过指定函数的测试,返回一个布尔值
      return data.cartList.every((item) => item.isChecked === 1)
    },
    // 计算订单总金额
    totalPrice(data) {
      // reduce() 方法对数组中的每个元素按序执行一个提供的 reducer 函数，每一次运行 reducer 会将先前元素的计算结果作为参数传入，最后将其结果汇总为单个返回值。
      return data.cartList.reduce((allPrice, item) => {
        return item.isChecked
          ? (allPrice += item.price * item.count)
          : allPrice
      }, 0)
    }
  },
  // 监视器
  watch: {
    // 当全选状态发生变化时，向服务器发请求更新全选状态
    selectAllStatus: async function (newVal) {
      await reqCheckAllStatus(newVal ? 1 : 0) // 该接口接收 0/1
    }
  },
  // 组件的方法列表
  methods: {
    // 由于使用的是Component构造的页面因此所有方法必须放在methods中
    // 更新商品购买状态
    async updateChecked(event) {
      // 获取最新的购买状态 event.detail
      let isChecked = event.detail ? 1 : 0 // true/false
      // 获取事件传递的参数 商品id，当前商品的下标
      const { goodsid, index } = event.target.dataset
      // 更新服务器商品购买状态
      await reqUpdateChecked(goodsid, isChecked)
      // 更新本地商品购买状态(修改本地数据/重新获取服务器中的数据)
      this.data.cartList[index].isChecked = isChecked // 更新数据不触发视图更新
      this.setData({
        cartList: this.data.cartList //触发视图更新
        // [`cartList[${index}].isChecked`]:isChecked // 同时进行更新
      })
    },
    // 更新商品的全选状态
    async updateSelectAllStatus() {
      // selectAllStatus为计算属性，不能直接进行修改，需要通过修改依赖计算的数据实现修改
      // map() 方法创建一个新数组，这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成
      this.data.selectAllStatus
        ? this.data.cartList.map((item) => (item.isChecked = 0))
        : this.data.cartList.map((item) => (item.isChecked = 1))
      // 响应式更新数据
      this.setData({
        cartList: this.data.cartList
      })
    },
    // 更新商品购买数量
    changeByNum: debounce(async function (event) {
      // 获取传递的事件参数 商品id、下标、之前购买数量
      const { goodsid, index, oldbuynum } = event.target.dataset
      // 获取最新的购买数量
      let newBuyNum = event.detail
      // 计算购买数量的差值
      let disCount = newBuyNum - oldbuynum
      // 如果购买数量没发生变化则无需进行更改
      if (disCount === 0) return
      // 发请求更新服务器端的购买数量(需要传递购买数量的差值)
      const result = await reqAddCart({
        goodsId: goodsid,
        count: disCount
      })
      // 将本地数据中的购买数量进行更新
      if (result.code === 200) {
        this.setData({
          [`cartList[${index}].count`]: newBuyNum,
          // 将商品变为选中状态
          [`cartList[${index}].isChecked`]: 1
        })
      }
    }, 500),
    // 获取购物车列表数据
    async getCartList() {
      const result = await reqCartList()
      // 对购物车列表商品进行存储,修改空状态文字
      this.setData({
        cartList: result.data,
        emptyDes:
          result.data.lenght === 0 ? '还没有添加商品，快去添加吧～' : ''
      })
    },
    // 删除购物车中商品的方法
    async deleteGoods(event) {
      // 获取事件函数传递的商品id
      const { goodsid } = event.target.dataset
      // 模态框提示用户是否删除
      const modalRes = await modal('提示', '你确定要删除该商品吗？') //true/false
      // 点击取消
      if (!modalRes) return
      // 点击确定
      const result = await reqDeleteGoods(goodsid)
      if (result.code === 200) {
        toast('删除成功~')
        // 重新获取购物车列表数据
        this.getCartList()
      }
    },
    // 点击去结算按钮回调
    toOrder() {
      // 判断用户是否选择了购买商品 总金额大于零
      if (this.data.totalPrice === 0) {
        toast('请选择要购买的商品')
        return
      }
      // 跳转到结算页面
      wx.navigateTo({
        url: '/modules/orderPayModule/pages/order/detail/detail'
      })
    },
    // 页面的生命周期也需要在methods中进行声明
    onShow() {
      // 此处使用onShow而不使用onLoad原因:在页面切换时需要重新获取商品列表的数据(tabbar页面切换时不会进行销毁)
      // 判断用户是否登录
      if (this.data.token) {
        // 获取商品列表数据
        this.getCartList()
      } else {
        // 设置空状态提示文字
        this.setData({
          emptyDes: '您尚未登录，点击登录获取更多权益'
        })
      }
    },
    // 购物车页面隐藏时需要将滑块弹回
    onHide() {
      // 调用 swiperCell behavior中的closeSwipe方法进行关闭
      this.closeSwipe()
    }
  }
})
